#include "device.h"
#include "stm32f4xx.h"
#include "device_types.h"

// Flash 寄存器定义
#define FLASH_BASE            ((uint32_t)0x40023C00)    /*!< FLASH base address */

// Flash 寄存器位定义
#define FLASH_ACR_LATENCY_Pos                (0U)                                
#define FLASH_ACR_LATENCY_Msk                (0xFUL << FLASH_ACR_LATENCY_Pos)    /*!< 0x0000000F */
#define FLASH_ACR_LATENCY                    FLASH_ACR_LATENCY_Msk               /*!< LATENCY[3:0] bits (Latency) */
#define FLASH_ACR_PRFTEN_Pos                 (8U)                                
#define FLASH_ACR_PRFTEN_Msk                 (0x1UL << FLASH_ACR_PRFTEN_Pos)     /*!< 0x00000100 */
#define FLASH_ACR_PRFTEN                     FLASH_ACR_PRFTEN_Msk                /*!< Prefetch enable */
#define FLASH_ACR_ICEN_Pos                   (9U)                                
#define FLASH_ACR_ICEN_Msk                   (0x1UL << FLASH_ACR_ICEN_Pos)       /*!< 0x00000200 */
#define FLASH_ACR_ICEN                       FLASH_ACR_ICEN_Msk                  /*!< Instruction cache enable */
#define FLASH_ACR_DCEN_Pos                   (10U)                               
#define FLASH_ACR_DCEN_Msk                   (0x1UL << FLASH_ACR_DCEN_Pos)       /*!< 0x00000400 */
#define FLASH_ACR_DCEN                       FLASH_ACR_DCEN_Msk                  /*!< Data cache enable */

#define FLASH_KEYR_KEY1                      ((uint32_t)0x45670123)              /*!< FLASH key1 */
#define FLASH_KEYR_KEY2                      ((uint32_t)0xCDEF89AB)              /*!< FLASH key2 */

#define FLASH_OPTKEYR_OPTKEY1                ((uint32_t)0x08192A3B)              /*!< FLASH option key1 */
#define FLASH_OPTKEYR_OPTKEY2                ((uint32_t)0x4C5D6E7F)              /*!< FLASH option key2 */

#define FLASH_SR_EOP_Pos                     (0U)                                
#define FLASH_SR_EOP_Msk                     (0x1UL << FLASH_SR_EOP_Pos)         /*!< 0x00000001 */
#define FLASH_SR_EOP                         FLASH_SR_EOP_Msk                    /*!< End of operation */
#define FLASH_SR_OPERR_Pos                   (1U)                                
#define FLASH_SR_OPERR_Msk                   (0x1UL << FLASH_SR_OPERR_Pos)       /*!< 0x00000002 */
#define FLASH_SR_OPERR                       FLASH_SR_OPERR_Msk                  /*!< Operation error */
#define FLASH_SR_WRPERR_Pos                  (4U)                                
#define FLASH_SR_WRPERR_Msk                  (0x1UL << FLASH_SR_WRPERR_Pos)      /*!< 0x00000010 */
#define FLASH_SR_WRPERR                      FLASH_SR_WRPERR_Msk                 /*!< Write protection error */
#define FLASH_SR_PGAERR_Pos                  (5U)                                
#define FLASH_SR_PGAERR_Msk                  (0x1UL << FLASH_SR_PGAERR_Pos)      /*!< 0x00000020 */
#define FLASH_SR_PGAERR                      FLASH_SR_PGAERR_Msk                 /*!< Programming alignment error */
#define FLASH_SR_PGPERR_Pos                  (6U)                                
#define FLASH_SR_PGPERR_Msk                  (0x1UL << FLASH_SR_PGPERR_Pos)      /*!< 0x00000040 */
#define FLASH_SR_PGPERR                      FLASH_SR_PGPERR_Msk                 /*!< Programming parallelism error */
#define FLASH_SR_PGSERR_Pos                  (7U)                                
#define FLASH_SR_PGSERR_Msk                  (0x1UL << FLASH_SR_PGSERR_Pos)      /*!< 0x00000080 */
#define FLASH_SR_PGSERR                      FLASH_SR_PGSERR_Msk                 /*!< Programming sequence error */
#define FLASH_SR_BSY_Pos                     (16U)                               
#define FLASH_SR_BSY_Msk                     (0x1UL << FLASH_SR_BSY_Pos)         /*!< 0x00010000 */
#define FLASH_SR_BSY                         FLASH_SR_BSY_Msk                    /*!< Busy */

#define FLASH_CR_PG_Pos                      (0U)                                
#define FLASH_CR_PG_Msk                      (0x1UL << FLASH_CR_PG_Pos)          /*!< 0x00000001 */
#define FLASH_CR_PG                          FLASH_CR_PG_Msk                     /*!< Programming */
#define FLASH_CR_SER_Pos                     (1U)                                
#define FLASH_CR_SER_Msk                     (0x1UL << FLASH_CR_SER_Pos)         /*!< 0x00000002 */
#define FLASH_CR_SER                         FLASH_CR_SER_Msk                    /*!< Sector Erase */
#define FLASH_CR_MER_Pos                     (2U)                                
#define FLASH_CR_MER_Msk                     (0x1UL << FLASH_CR_MER_Pos)         /*!< 0x00000004 */
#define FLASH_CR_MER                         FLASH_CR_MER_Msk                    /*!< Mass Erase */
#define FLASH_CR_SNB_Pos                     (3U)                                
#define FLASH_CR_SNB_Msk                     (0xFUL << FLASH_CR_SNB_Pos)         /*!< 0x00000078 */
#define FLASH_CR_SNB                         FLASH_CR_SNB_Msk                    /*!< Sector number */
#define FLASH_CR_PSIZE_Pos                   (8U)                                
#define FLASH_CR_PSIZE_Msk                   (0x3UL << FLASH_CR_PSIZE_Pos)       /*!< 0x00000300 */
#define FLASH_CR_PSIZE                       FLASH_CR_PSIZE_Msk                  /*!< Program size */
#define FLASH_CR_STRT_Pos                    (16U)                               
#define FLASH_CR_STRT_Msk                    (0x1UL << FLASH_CR_STRT_Pos)        /*!< 0x00010000 */
#define FLASH_CR_STRT                        FLASH_CR_STRT_Msk                   /*!< Start */
#define FLASH_CR_LOCK_Pos                    (31U)                               
#define FLASH_CR_LOCK_Msk                    (0x1UL << FLASH_CR_LOCK_Pos)        /*!< 0x80000000 */
#define FLASH_CR_LOCK                        FLASH_CR_LOCK_Msk                   /*!< Lock */

// Flash 操作状态定义
typedef enum
{ 
  FLASH_BUSY = 1,
  FLASH_ERROR_PGS,
  FLASH_ERROR_PGP,
  FLASH_ERROR_PGA,
  FLASH_ERROR_WRP,
  FLASH_ERROR_PROGRAM,
  FLASH_ERROR_OPERATION,
  FLASH_COMPLETE
} flash_status_e;

// Flash 编程大小定义
#define FLASH_PSIZE_BYTE               ((uint32_t)0x00000000)
#define FLASH_PSIZE_HALF_WORD          ((uint32_t)0x00000100)
#define FLASH_PSIZE_WORD               ((uint32_t)0x00000200)
#define FLASH_PSIZE_DOUBLE_WORD        ((uint32_t)0x00000300)
#define CR_PSIZE_MASK                  ((uint32_t)0xFFFFFCFF)

// Flash 电压范围定义
#define VoltageRange_1                 ((uint8_t)0x00)  /*!<Device operating range: 1.8V to 2.1V */
#define VoltageRange_2                 ((uint8_t)0x01)  /*!<Device operating range: 2.1V to 2.7V */
#define VoltageRange_3                 ((uint8_t)0x02)  /*!<Device operating range: 2.7V to 3.6V */
#define VoltageRange_4                 ((uint8_t)0x03)  /*!<Device operating range: 2.7V to 3.6V + External Vpp */


#define SECTOR_MASK                    ((uint32_t)0xFFFFFF07)

#define RDP_KEY                        ((uint16_t)0x00A5)

#define FLASH_FLAG_EOP                 ((uint32_t)0x00000001)  /*!< FLASH End of Operation flag */
#define FLASH_FLAG_OPERR               ((uint32_t)0x00000002)  /*!< FLASH operation Error flag */
#define FLASH_FLAG_WRPERR              ((uint32_t)0x00000010)  /*!< FLASH Write protected error flag */
#define FLASH_FLAG_PGAERR              ((uint32_t)0x00000020)  /*!< FLASH Programming Alignment error flag */
#define FLASH_FLAG_PGPERR              ((uint32_t)0x00000040)  /*!< FLASH Programming Parallelism error flag  */
#define FLASH_FLAG_PGSERR              ((uint32_t)0x00000080)  /*!< FLASH Programming Sequence error flag  */
#define FLASH_FLAG_BSY                 ((uint32_t)0x00010000)  /*!< FLASH Busy flag */ 
#define IS_FLASH_CLEAR_FLAG(FLAG)      ((((FLAG) & (uint32_t)0xFFFFFF0C) == 0x00000000) && ((FLAG) != 0x00000000))

// 解锁 Flash
void flash_ll_unlock(void) {
    if (FLASH->CR & FLASH_CR_LOCK) {
        FLASH->KEYR = FLASH_KEYR_KEY1;
        FLASH->KEYR = FLASH_KEYR_KEY2;
    }
}

// 上锁 Flash
void flash_ll_lock(void) {
    FLASH->CR |= FLASH_CR_LOCK;
}

void flash_delay(unsigned int x)
{
  while(x > 0){
    for(int i = 0;i < 2000;i++);
    x--;
  }
}


flash_status_e flash_get_status(void)
{
  flash_status_e flashstatus = FLASH_COMPLETE;
  
  if((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY) 
  {
    flashstatus = FLASH_BUSY;
  }
  else 
  {  
    if((FLASH->SR & FLASH_SR_WRPERR) != (uint32_t)0x00)
    { 
      flashstatus = FLASH_ERROR_WRP;
    }
    else 
    {
      if((FLASH->SR & (uint32_t)0xEF) != (uint32_t)0x00)
      {
        flashstatus = FLASH_ERROR_PROGRAM; 
      }
      else
      {
        if((FLASH->SR & FLASH_SR_OPERR) != (uint32_t)0x00)
        {
          flashstatus = FLASH_ERROR_OPERATION;
        }
        else
        {
          flashstatus = FLASH_COMPLETE;
        }
      }
    }
  }
  /* Return the FLASH Status */
  return flashstatus;
}

flash_status_e flash_wait(void)
{ 
  __IO flash_status_e status = FLASH_COMPLETE;
   
  /* Check for the FLASH Status */
  status = flash_get_status();

  /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
     Even if the FLASH operation fails, the BUSY flag will be reset and an error
     flag will be set */
  while(status == FLASH_BUSY)
  {
    flash_delay(5);
    status = flash_get_status();
  }
  /* Return the operation status */
  return status;
}


int flash_get_sector(struct flash_describer_s *desc, uint32_t Address)
{
    int sector = -1;

    for(int i = 0; i < desc->sector_num; i++){
        if(Address >= desc->sectors[i].addr && Address < desc->sectors[i].addr + desc->sectors[i].size){
            sector = i;
            break;
        }
    }
    return sector;
}


flash_status_e flash_erase_sector(uint32_t FLASH_Sector, uint8_t VoltageRange)
{
  uint32_t tmp_psize = 0x0;
  flash_status_e status = FLASH_COMPLETE;

  if(VoltageRange == VoltageRange_1)
  {
     tmp_psize = FLASH_PSIZE_BYTE;
  }
  else if(VoltageRange == VoltageRange_2)
  {
    tmp_psize = FLASH_PSIZE_HALF_WORD;
  }
  else if(VoltageRange == VoltageRange_3)
  {
    tmp_psize = FLASH_PSIZE_WORD;
  }
  else
  {
    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
  }
  /* Wait for last operation to be completed */
  status = flash_wait();
  
  if(status == FLASH_COMPLETE)
  { 
    /* if the previous operation is completed, proceed to erase the sector */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= tmp_psize;
    FLASH->CR &= ~FLASH_CR_SNB;
    FLASH->CR |= (FLASH_Sector << 3);
    FLASH->CR |= FLASH_CR_SER;
    FLASH->CR |= FLASH_CR_STRT;
    
    /* Wait for last operation to be completed */
    status = flash_wait();
    
    /* if the erase operation is completed, disable the SER Bit */
    FLASH->CR &= ~FLASH_CR_SER;
    FLASH->CR &= ~FLASH_CR_SNB;
  }
  /* Return the Erase Status */
  return status;
}

flash_status_e flash_program_byte(uint32_t Address, uint8_t Data)
{
  flash_status_e status = FLASH_COMPLETE;

  /* Wait for last operation to be completed */
  status = flash_wait();
  
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new data */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= FLASH_PSIZE_BYTE;
    FLASH->CR |= FLASH_CR_PG;
  
    *(__IO uint8_t*)Address = Data;
        
    /* Wait for last operation to be completed */
    status = flash_wait();

    /* if the program operation is completed, disable the PG Bit */
    FLASH->CR &= (~FLASH_CR_PG);
  } 

  /* Return the Program Status */
  return status;
}

flash_status_e flash_program_word(uint32_t Address, uint32_t Data)
{
  flash_status_e status = FLASH_COMPLETE;

  /* Wait for last operation to be completed */
  status = flash_wait();
  
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new data */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= FLASH_PSIZE_WORD;
    FLASH->CR |= FLASH_CR_PG;
  
    *(__IO uint32_t*)Address = Data;
        
    /* Wait for last operation to be completed */
    status = flash_wait();

    /* if the program operation is completed, disable the PG Bit */
    FLASH->CR &= (~FLASH_CR_PG);
  } 
  /* Return the Program Status */
  return status;
}


static int32_t flash_read(struct lt_dev_s *dev, void *buffer, int32_t buflen, int32_t pos)
{
    uint32_t *data = (uint32_t *)buffer;
    uint32_t addr = (uint32_t)pos;
    int i;
    int read_len;
    
    struct flash_describer_s *desc = (struct flash_describer_s *)dev->priv_data;
    
    // 检查参数
    if (!buffer || buflen <= 0 || pos < 0) {
        return -1;
    }
    
    // 检查是否超出 Flash 地址范围
    if (addr + buflen > desc->sectors[desc->sector_num - 1].addr + desc->sectors[desc->sector_num - 1].size) {
        return -1;
    }
    
    // 确保地址 4 字节对齐
    if (addr & 0x3) {
        return -1;
    }
    
    // 计算实际读取长度（按字对齐）
    read_len = (buflen + 3) & ~0x3;
    if (read_len > buflen) {
        read_len = buflen;
    }
    
    // 读取数据
    for (i = 0; i < read_len; i += 4) {
        *data = *((volatile uint32_t *)addr);
        data++;
        addr += 4;
    }
    
    return read_len;
}

static int32_t flash_init(struct lt_dev_s *dev)
{
    return 0;
}

static int32_t flash_open(struct lt_dev_s *dev, uint16_t flag)
{
    flash_ll_lock(); 
    return 0;
}


static int32_t flash_ioctl(struct lt_dev_s *dev, uint32_t cmd, void *arg)
{
    struct flash_program_s *prog;
    int ret = 0;
    uint32_t sector;
    struct flash_describer_s *desc = (struct flash_describer_s *)dev->priv_data;

    switch(cmd) {
        case FLASH_CTRL_LOCK:
            flash_ll_lock();
            break;

        case FLASH_CTRL_UNLOCK:
            flash_ll_unlock();
            break;

        case FLASH_CTRL_ERASE_SECTOR:
            sector = *(uint32_t *)arg;
            ret = flash_erase_sector(sector, VoltageRange_3);
            break;

        case FLASH_CTRL_ERASE_ALL:
            // 解锁 Flash
            flash_ll_unlock();
            
            // 擦除所有扇区
            for (int i = 2; i < desc->sector_num; i++) {
                ret = flash_erase_sector(i, VoltageRange_3);
                if (ret != FLASH_COMPLETE) {
                    break;
                }
            }
            
            // 锁定 Flash
            flash_ll_lock();
            break;

        case FLASH_CTRL_PROGRAM_WORD:
            prog = (struct flash_program_s *)arg;
            ret = flash_program_word(prog->addr, prog->data);
            break;

        case FLASH_CTRL_PROGRAM_HALF:
            prog = (struct flash_program_s *)arg;
            // 读取当前字
            uint32_t current_word = *(__IO uint32_t *)prog->addr;
            // 根据地址对齐修改半字
            if (prog->addr & 0x02) {
                current_word = (current_word & 0x0000FFFF) | (prog->data << 16);
            } else {
                current_word = (current_word & 0xFFFF0000) | prog->data;
            }
            ret = flash_program_word(prog->addr & 0xFFFFFFFC, current_word);
            break;

        default:
            ret = -1;
            break;
    }

    return ret;
}


struct flash_sector_s stm32f405_sectors[12] = {
    {.addr = 0x08000000, .size = 16 * 1024},
    {.addr = 0x08004000, .size = 16 * 1024},
    {.addr = 0x08008000, .size = 16 * 1024},
    {.addr = 0x0800C000, .size = 16 * 1024},
    {.addr = 0x08010000, .size = 64 * 1024},
    {.addr = 0x08020000, .size = 128 * 1024},
    {.addr = 0x08040000, .size = 128 * 1024},
    {.addr = 0x08060000, .size = 128 * 1024},
    {.addr = 0x08080000, .size = 128 * 1024},
    {.addr = 0x080A0000, .size = 128 * 1024},
    {.addr = 0x080C0000, .size = 128 * 1024},
    {.addr = 0x080E0000, .size = 128 * 1024},
};

struct flash_describer_s stm32f405_desc = {
    .sector_num = 12,
    .sectors = stm32f405_sectors
};

struct lt_dev_s flash_dev;

static int32_t flash_close(struct lt_dev_s *dev)
{
    // 确保 Flash 被锁定
    flash_ll_lock();
    return 0;
}

int32_t flash_dev_register(void)
{
    flash_dev.open = flash_open;
    flash_dev.read = flash_read;
    flash_dev.ioctl = flash_ioctl;
    flash_dev.close = flash_close;  // 添加 close 函数
    flash_dev.priv_data = &stm32f405_desc;
    flash_dev.init = flash_init;
    
    return lt_dev_register(&flash_dev, "flash", O_RDWR);
}



